package com.tang.portal.facade.admin.log;

import com.tang.framework.core.domain.HttpResult;
import com.tang.framework.core.facade.Facade;
import com.tang.log.domain.AdminErrorLog;
import com.tang.log.domain.AdminSuccessLog;
import com.tang.log.domain.AppErrorLog;
import com.tang.log.domain.AppSuccessLog;
import com.tang.log.model.req.ReqLogSearch;
import com.tang.log.model.res.RequestResponseTimeLine;
import com.tang.log.model.res.RequestStatistics;
import com.tang.log.repository.AdminErrorLogRepository;
import com.tang.log.repository.AdminSuccessLogRepository;
import com.tang.log.repository.AppErrorLogRepository;
import com.tang.log.repository.AppSuccessLogRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author tang jun liang
 * @Date 2023/5/20 22:29
 */
@Service
public class RequestLogFacade extends Facade {

    @Resource
    private AdminSuccessLogRepository adminSuccessLogRepository;


    @Resource
    private AdminErrorLogRepository adminErrorLogRepository;


    @Resource
    private AppSuccessLogRepository appSuccessLogRepository;


    @Resource
    private AppErrorLogRepository appErrorLogRepository;


    @Resource
    private MongoTemplate mongoTemplate;


    public Page<AdminSuccessLog> adminSuccessLogList(ReqLogSearch logSearch) {
        Pageable pageable = PageRequest.of((int) (logSearch.getPageNum() - 1), (int) logSearch.getPageSize());
        if (Objects.isNull(logSearch.getTime()) && Objects.isNull(logSearch.getExecuteTime())) {
            return adminSuccessLogRepository.findByOrderByExecuteTimeDesc(pageable);
        }
        return null;
    }

    public HttpResult<RequestStatistics> statistics() {
        RequestStatistics requestStatistics = new RequestStatistics();
        LocalDate localDate = LocalDate.now();
        LocalDateTime start = LocalDateTime.of(localDate, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(localDate, LocalTime.MAX);
        Criteria criteria = new Criteria();
        Criteria executeTime = criteria.and("executeTime");
        executeTime.gte(start);
        executeTime.lte(end);
        List<AdminSuccessLog> adminSuccessLogs = mongoTemplate.find(new Query(criteria), AdminSuccessLog.class);
        List<AppSuccessLog> appSuccessLogs = mongoTemplate.find(new Query(criteria), AppSuccessLog.class);
        LongSummaryStatistics longSummaryStatistics = Stream.concat(adminSuccessLogs.stream().map(AdminSuccessLog::getTime), appSuccessLogs.stream().map(AppSuccessLog::getTime))
                .collect(Collectors.summarizingLong(Long::longValue));
        requestStatistics.setResponseTime(longSummaryStatistics.getAverage());
        List<AdminErrorLog> adminErrorLogs = mongoTemplate.find(new Query(criteria), AdminErrorLog.class);
        List<AppErrorLog> appErrorLogs = mongoTemplate.find(new Query(criteria), AppErrorLog.class);
        requestStatistics.setTodayErrorNum(adminErrorLogs.size() + appErrorLogs.size());
        requestStatistics.setTodayNum(longSummaryStatistics.getCount() + requestStatistics.getTodayErrorNum());
        LocalDateTime now = LocalDateTime.now();
        // 获取当前时间戳（以秒为单位）
        long currentTimestamp = now.toEpochSecond(ZoneOffset.ofHours(8));
        // 获取当天开始时间的时间戳（以秒为单位）
        long startOfDayTimestamp = start.toEpochSecond(ZoneOffset.ofHours(8));
        requestStatistics.setSecondNum(requestStatistics.getTodayNum() / (currentTimestamp - startOfDayTimestamp));
        LocalDateTime oneHoursBegin = now.plusHours(-1L);
        Long recentHourNum = Stream.concat(Stream.concat(adminSuccessLogs.stream()
                                .filter(item -> (item.getExecuteTime().isBefore(now) &&
                                        item.getExecuteTime().isAfter(oneHoursBegin)) ||
                                        item.getExecuteTime().isEqual(now) || item.getExecuteTime().isEqual(oneHoursBegin)),
                        adminErrorLogs.stream().filter(item -> item.getExecuteTime()
                                .isBefore(now) && item.getExecuteTime().isAfter(oneHoursBegin) ||
                                item.getExecuteTime().isEqual(now) || item.getExecuteTime().isEqual(oneHoursBegin))),
                Stream.concat(appSuccessLogs.stream().filter(item -> item.getExecuteTime().
                                isBefore(now) && item.getExecuteTime().isAfter(oneHoursBegin) ||
                                item.getExecuteTime().isEqual(now) || item.getExecuteTime().isEqual(oneHoursBegin)),
                        appErrorLogs.stream().filter(item ->
                                item.getExecuteTime().isBefore(now) && item.getExecuteTime().
                                        isAfter(oneHoursBegin) || item.getExecuteTime().isEqual(now) ||
                                        item.getExecuteTime().isEqual(oneHoursBegin)))).count();
        requestStatistics.setRecentHourNum(recentHourNum);
        return ok(requestStatistics);

    }

    public HttpResult<List<RequestResponseTimeLine>> responseTimeLine() {
        List<RequestResponseTimeLine> responseTimeLines = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        Criteria criteria = new Criteria();
        Criteria executeTime = criteria.and("executeTime");
        executeTime.gte(now.plusHours(-5L));
        executeTime.lte(now);
        List<AdminSuccessLog> adminSuccessLogs = mongoTemplate.find(new Query(criteria), AdminSuccessLog.class);
        List<AppSuccessLog> appSuccessLogs = mongoTemplate.find(new Query(criteria), AppSuccessLog.class);
        Stream.concat(adminSuccessLogs.stream().map(item -> new HashMap<String, Long>() {{
                            put(item.getExecuteTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH")), item.getTime());
                        }})
                        , appSuccessLogs.stream().map(item -> new HashMap<String, Long>() {{
                            put(item.getExecuteTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH")), item.getTime());
                        }}))
                .collect(Collectors.groupingBy(item -> item.keySet().stream().limit(1).findFirst().orElse(""))).forEach((key, value) -> {
                    RequestResponseTimeLine responseTimeLine = new RequestResponseTimeLine();
                    responseTimeLine.setHour(key);
//                    responseTimeLine.setHour();
                });

        return ok(responseTimeLines);
    }
}
